package de.rj.urwalking.data.survey;

import android.app.Activity;
import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnFocusChangeListener;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.TextView;
import de.rj.urwalking.R;
import de.rj.urwalking.config.Config;
import de.rj.urwalking.config.Constants;
import de.rj.urwalking.data.Experiment;

/**
 * 
 * This CategoryQuestion allows the user to choose one of several given options. Additionally, there is an option
 * combined with a text field for user input.
 * 
 * @author rjj
 * 
 */

public class CategoryQuestion extends Question {

	private static final long serialVersionUID = 1L;
	private int freeTextId; // id of the RadioButton that enables free text input
	protected boolean hasEnteredText = false;
	private transient RadioGroup radioGroup;
	private int surveyType;

	public CategoryQuestion(int id, int itemNumber, String text, int scaleId, int screen) {
		super(id, itemNumber, text, scaleId, screen);

	}

	@Override
	public View buildView(final Context context, ViewGroup parent) {

		// build UI from xml layout
		LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		View questionView = inflater.inflate(R.layout.question_multiple_choice, parent, false);

		// show question text
		TextView questionText = (TextView) questionView.findViewById(R.id.questionText);
		questionText.setText(getText());

		// set up text field
		final EditText freeTextEditText = (EditText) questionView.findViewById(R.id.freeTextEditText);
		freeTextEditText.addTextChangedListener(new TextWatcher() {

			@Override
			public void onTextChanged(CharSequence s, int start, int before, int count) {
				if (s.toString().equals("")) {
					hasEnteredText = false;
				} else {
					hasEnteredText = true;
				}
				mCallback.onAnswerChanged();
			}

			@Override
			public void beforeTextChanged(CharSequence s, int start, int count, int after) {
			}

			@Override
			public void afterTextChanged(Editable s) {

			}
		});

		freeTextEditText.setOnFocusChangeListener(new OnFocusChangeListener() {

			@Override
			public void onFocusChange(View v, boolean hasFocus) {

				if (!hasFocus && radioGroup.getCheckedRadioButtonId() == freeTextId) {
					InputMethodManager imm = (InputMethodManager) context
							.getSystemService(Context.INPUT_METHOD_SERVICE);
					imm.hideSoftInputFromWindow(v.getWindowToken(), 0);

					// save answer every time the user changes it
					updateAnswer(freeTextId, freeTextEditText.getText().toString());
				}
			}
		});

		radioGroup = (RadioGroup) questionView.findViewById(R.id.radioGroup);

		// add RadioButtons to RadioGroup programmatically since their number
		// isn't fixed
		for (int i = 0; i < scalePoints.size(); i++) {

			if (surveyType == Experiment.TYPE_OUTDOOR && scalePoints.get(i).isIndoor()) {
				continue;
			} else if (surveyType == Experiment.TYPE_INDOOR && scalePoints.get(i).isOutdoor()) {
				continue;
			}

			RadioButton radioButton = new RadioButton(context);
			radioButton.setText(scalePoints.get(i).getTitle());
			radioButton.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
			radioButton.setId(scalePoints.get(i).getIntValue());
			radioGroup.addView(radioButton);

			// FIXME: nasty hack to mark "Sonstiges" as free text input. As soon
			// as it is supported by the DB, read it
			// from there!

			if (needsFreeText(scalePoints.get(i).getIntValue())) {
				freeTextId = scalePoints.get(i).getIntValue();
			}
		}

		radioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() {

			@Override
			public void onCheckedChanged(RadioGroup group, int checkedId) {

				if (checkedId == -1) return;

				// enable editText if "Sonstiges" is checked
				if (checkedId == freeTextId) {
					updateAnswer(checkedId, freeTextEditText.getText().toString());
					freeTextEditText.setEnabled(true);
					freeTextEditText.requestFocus();
					InputMethodManager imm = (InputMethodManager) ((Activity) context)
							.getSystemService(Context.INPUT_METHOD_SERVICE);
					imm.showSoftInput(freeTextEditText, InputMethodManager.SHOW_IMPLICIT);
				} else {
					updateAnswer(checkedId);
					freeTextEditText.setEnabled(false);
				}

			}
		});

		// restore the previous state
		if (getAnswer().getIntAnswer() == Constants.UNDEFINED) {
			radioGroup.clearCheck();
		} else if (getAnswer().getIntAnswer() == freeTextId) {
			freeTextEditText.setEnabled(true);
			freeTextEditText.setText(getAnswer().getTextAnswer());
			radioGroup.check(getAnswer().getIntAnswer());
		} else {
			radioGroup.check(getAnswer().getIntAnswer());
		}

		return questionView;
	}

	private boolean needsFreeText(int intValue) {

		for (int scalePoint : Config.SCALEPOINTS_OTHER) {
			if (intValue == scalePoint) {
				return true;
			}
		}
		return false;
	}

	@Override
	public boolean hasBeenAnswered() {

		// This MultipleChoiceQuestion is considered as answered if either
		// a. the free text option "Sonstiges" is chosen and some input is given
		// or
		// b. any other option is chosen

		if (getAnswer().getIntAnswer() == Constants.UNDEFINED) {
			return false;
		} else if (getAnswer().getIntAnswer() == freeTextId && !hasEnteredText) {
			return false;
		} else {
			return true;
		}
	}

	/**
	 * Tells this question if it's in an indoor or outdoor survey.
	 * 
	 * @param surveyType
	 */
	public void setSurveyType(int surveyType) {

		this.surveyType = surveyType;
	}

}
